home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / cvs / sprite / RCS / subr.c,v < prev    next >
Encoding:
Text File  |  1991-11-04  |  8.3 KB  |  410 lines

  1. head     1.1;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    jhh:1.1; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.1
  10. date     91.11.03.18.31.05;  author jhh;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @@
  17.  
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @#ifndef lint
  26. static char rcsid[] = "$Id: subr.c,v 1.14.1.2 91/01/29 19:46:20 berliner Exp $";
  27. #endif !lint
  28.  
  29. /*
  30.  *    Copyright (c) 1989, Brian Berliner
  31.  *
  32.  *    You may distribute under the terms of the GNU General Public License
  33.  *    as specified in the README file that comes with the CVS 1.0 kit.
  34.  *
  35.  * Various useful functions for the CVS support code.
  36.  */
  37.  
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <sys/file.h>
  41. #include <varargs.h>
  42. #include "cvs.h"
  43.  
  44. /*
  45.  * Send a "printf" format string to stderr and die, calling the
  46.  * defined exit function first, if necessary
  47.  */
  48. error(doperror, fmt, va_alist)
  49.     int doperror;
  50.     char *fmt;
  51.     va_dcl
  52. {
  53.     extern int errno;
  54.     va_list x1;
  55.     int err = errno;
  56.  
  57.     va_start(x1);
  58.     (void) fprintf(stderr, "%s: ", progname);
  59.     (void) vfprintf(stderr, fmt, x1);
  60.     if (doperror) {
  61.     (void) fprintf(stderr, ": ");
  62.     errno = err;
  63.     perror("");
  64.     errno = 0;
  65.     } else
  66.     (void) fprintf(stderr, "\n");
  67.     va_end(x1);
  68.     Lock_Cleanup(0);
  69.     exit(1);
  70. }
  71.  
  72. /*
  73.  * Like error() above, but just display the message to stderr,
  74.  * without dying or running the exit function.
  75.  */
  76. warn(doperror, fmt, va_alist)
  77.     int doperror;
  78.     char *fmt;
  79.     va_dcl
  80. {
  81.     extern int errno;
  82.     va_list x1;
  83.     int err = errno;
  84.  
  85.     va_start(x1);
  86.     (void) fprintf(stderr, "%s: ", progname);
  87.     (void) vfprintf(stderr, fmt, x1);
  88.     if (doperror) {
  89.     (void) fprintf(stderr, ": ");
  90.     errno = err;
  91.     perror("");
  92.     errno = 0;
  93.     } else
  94.     (void) fprintf(stderr, "\n");
  95.     va_end(x1);
  96. }
  97.  
  98. /*
  99.  * Copies "from" to "to".
  100.  * mallocs a buffer large enough to hold the entire file and
  101.  * does one read/one write to do the copy.  This is reasonable,
  102.  * since source files are typically not too large.
  103.  */
  104. copy_file(from, to)
  105.     char *from;
  106.     char *to;
  107. {
  108.     struct stat sb;
  109.     int fdin, fdout;
  110.     char *buf;
  111.  
  112.     if ((fdin = open(from, O_RDONLY)) < 0)
  113.     error(1, "cannot open %s for copying", from);
  114.     if (fstat(fdin, &sb) < 0)
  115.     error(1, "cannot fstat %s", from);
  116.     if ((fdout = creat(to, (int) sb.st_mode & 07777)) < 0)
  117.     error(1, "cannot create %s for copying", to);
  118.     if (sb.st_size > 0) {
  119.     buf = xmalloc((int)sb.st_size);
  120.     if (read(fdin, buf, (int)sb.st_size) != (int)sb.st_size)
  121.         error(1, "cannot read file %s for copying", from);
  122.     if (write(fdout, buf, (int)sb.st_size) != (int)sb.st_size)
  123.         error(1, "cannot write file %s for copying", to);
  124.     free(buf);
  125.     }
  126.     (void) close(fdin);
  127.     (void) close(fdout);
  128. }
  129.  
  130. /*
  131.  * Returns non-zero if the argument file is a directory, or
  132.  * is a symbolic link which points to a directory.
  133.  */
  134. isdir(file)
  135.     char *file;
  136. {
  137.     struct stat sb;
  138.  
  139.     if (stat(file, &sb) < 0)
  140.     return (0);
  141.     return ((sb.st_mode & S_IFMT) == S_IFDIR);
  142. }
  143.  
  144. /*
  145.  * Returns non-zero if the argument file is a symbolic link.
  146.  */
  147. islink(file)
  148.     char *file;
  149. {
  150.     struct stat sb;
  151.  
  152. #ifdef S_IFLNK
  153.     if (lstat(file, &sb) < 0)
  154.     return (0);
  155.     return ((sb.st_mode & S_IFMT) == S_IFLNK);
  156. #else
  157.     return (0);
  158. #endif
  159. }
  160.  
  161. /*
  162.  * Returns non-zero if the argument file exists.
  163.  */
  164. isfile(file)
  165.     char *file;
  166. {
  167.     struct stat sb;
  168.  
  169.     if (stat(file, &sb) < 0)
  170.     return (0);
  171.     return (1);
  172. }
  173.  
  174. /*
  175.  * Returns non-zero if the argument file is readable.
  176.  * XXX - muct be careful if "cvs" is ever made setuid!
  177.  */
  178. isreadable(file)
  179.     char *file;
  180. {
  181.     return (access(file, R_OK) != -1);
  182. }
  183.  
  184. /*
  185.  * Returns non-zero if the argument file is writable
  186.  * XXX - muct be careful if "cvs" is ever made setuid!
  187.  */
  188. iswritable(file)
  189.     char *file;
  190. {
  191.     return (access(file, W_OK) != -1);
  192. }
  193.  
  194. /*
  195.  * Open a file and die if it fails
  196.  */
  197. FILE *
  198. open_file(name, mode)
  199.     char *name;
  200.     char *mode;
  201. {
  202.     FILE *fp;
  203.  
  204.     if ((fp = fopen(name, mode)) == NULL)
  205.     error(1, "cannot open %s", name);
  206.     return (fp);
  207. }
  208.  
  209. /*
  210.  * Make a directory and die if it fails
  211.  */
  212. make_directory(name)
  213.     char *name;
  214. {
  215.     if (mkdir(name, 0777) < 0)
  216.     error(1, "cannot make directory %s", name);
  217. }
  218.  
  219. /*
  220.  * malloc some data and die if it fails
  221.  */
  222. char *
  223. xmalloc(bytes)
  224.     int bytes;
  225. {
  226.     extern char *malloc();
  227.     char *cp;
  228.  
  229.     if (bytes <= 0)
  230.     error(0, "bad malloc size %d", bytes);
  231.     if ((cp = malloc((unsigned)bytes)) == NULL)
  232.     error(0, "malloc failed");
  233.     return (cp);
  234. }
  235.  
  236.  
  237. /*
  238.  * ppstrcmp() is a front-end for strcmp() when the arguments
  239.  * are pointers to pointers to chars.
  240.  */
  241. ppstrcmp(pp1, pp2)
  242.     register char **pp1, **pp2;
  243. {
  244.     return (strcmp(*pp1, *pp2));
  245. }
  246.  
  247. /*
  248.  * ppstrcmp_files() is a front-end for strcmp() when the arguments
  249.  * are pointers to pointers to chars.
  250.  * For some reason, the ppstrcmp() above sorts in reverse order when
  251.  * called from Entries2Files().
  252.  */
  253. ppstrcmp_files(pp1, pp2)
  254.     register char **pp1, **pp2;
  255. {
  256.     /*
  257.      * Reversing the arguments here cause for the
  258.      * correct alphabetical order sort, as we desire.
  259.      */
  260.     return (strcmp(*pp2, *pp1));
  261. }
  262.  
  263. /* Some UNIX distributions don't include these in their stat.h */
  264. #ifndef S_IWRITE
  265. #define    S_IWRITE    0000200        /* write permission, owner */
  266. #endif !S_IWRITE
  267. #ifndef S_IWGRP
  268. #define    S_IWGRP        0000020        /* write permission, grougroup */
  269. #endif !S_IWGRP
  270. #ifndef S_IWOTH
  271. #define    S_IWOTH        0000002        /* write permission, other */
  272. #endif !S_IWOTH
  273.  
  274. /*
  275.  * Change the mode of a file, either adding write permissions, or
  276.  * removing all write permissions.  Adding write permissions honors
  277.  * the current umask setting.
  278.  */
  279. xchmod(fname, writable)
  280.     char *fname;
  281.     int writable;
  282. {
  283.     struct stat sb;
  284.     int mode, oumask;
  285.  
  286.     if (stat(fname, &sb) < 0) {
  287.     warn(1, "cannot stat %s", fname);
  288.     return;
  289.     }
  290.     if (writable) {
  291.     oumask = umask(0);
  292.     (void) umask(oumask);
  293.     mode = sb.st_mode | ((S_IWRITE|S_IWGRP|S_IWOTH) & ~oumask);
  294.     } else {
  295.     mode = sb.st_mode & ~(S_IWRITE|S_IWGRP|S_IWOTH);
  296.     }
  297.     if (chmod(fname, mode) < 0)
  298.     warn(1, "cannot change mode of file %s", fname);
  299. }
  300.  
  301. /*
  302.  * Rename a file and die if it fails
  303.  */
  304. rename_file(from, to)
  305.     char *from;
  306.     char *to;
  307. {
  308.     if (rename(from, to) < 0)
  309.     error(1, "cannot rename file %s to %s", from, to);
  310. }
  311.  
  312. /*
  313.  * Compare "file1" to "file2".
  314.  * Return non-zero if they don't compare exactly.
  315.  *
  316.  * mallocs a buffer large enough to hold the entire file and
  317.  * does two reads to load the buffer and calls bcmp to do the cmp.
  318.  * This is reasonable, since source files are typically not too large.
  319.  */
  320. xcmp(file1, file2)
  321.     char *file1;
  322.     char *file2;
  323. {
  324.     register char *buf1, *buf2;
  325.     struct stat sb;
  326.     off_t size;
  327.     int ret, fd1, fd2;
  328.  
  329.     if ((fd1 = open(file1, O_RDONLY)) < 0)
  330.     error(1, "cannot open file %s for comparing", file1);
  331.     if ((fd2 = open(file2, O_RDONLY)) < 0)
  332.     error(1, "cannot open file %s for comparing", file2);
  333.     if (fstat(fd1, &sb) < 0)
  334.     error(1, "cannot fstat %s", file1);
  335.     size = sb.st_size;
  336.     if (fstat(fd2, &sb) < 0)
  337.     error(1, "cannot fstat %s", file2);
  338.     if (size == sb.st_size) {
  339.     if (size == 0)
  340.         ret = 0;
  341.     else {
  342.         buf1 = xmalloc((int)size);
  343.         buf2 = xmalloc((int)size);
  344.         if (read(fd1, buf1, (int)size) != (int)size)
  345.         error(1, "cannot read file %s cor comparing", file1);
  346.         if (read(fd2, buf2, (int)size) != (int)size)
  347.         error(1, "cannot read file %s for comparing", file2);
  348.         ret = bcmp(buf1, buf2, (int)size);
  349.         free(buf1);
  350.         free(buf2);
  351.     }
  352.     } else
  353.     ret = 1;
  354.     (void) close(fd1);
  355.     (void) close(fd2);
  356.     return (ret);
  357. }
  358.  
  359. /*
  360.  * Recover the space allocated by Find_Names() and line2argv()
  361.  */
  362. free_names(pargc, argv)
  363.     int *pargc;
  364.     char *argv[];
  365. {
  366.     register int i;
  367.  
  368.     for (i = 0; i < *pargc; i++) {    /* only do through *pargc */
  369.     free(argv[i]);
  370.     }
  371.     *pargc = 0;                /* and set it to zero when done */
  372. }
  373.  
  374. /*
  375.  * Convert a line into argc/argv components and return the result in
  376.  * the arguments as passed.  Use free_names() to return the memory
  377.  * allocated here back to the free pool.
  378.  */
  379. line2argv(pargc, argv, line)
  380.     int *pargc;
  381.     char *argv[];
  382.     char *line;
  383. {
  384.     char *cp;
  385.  
  386.     *pargc = 0;
  387.     for (cp = strtok(line, " \t"); cp; cp = strtok((char *)NULL, " \t")) {
  388.     argv[*pargc] = xmalloc(strlen(cp) + 1);
  389.     (void) strcpy(argv[*pargc], cp);
  390.     (*pargc)++;
  391.     }
  392. }
  393.  
  394. /*
  395.  * Returns the number of dots ('.') found in an RCS revision number
  396.  */
  397. numdots(s)
  398.     char *s;
  399. {
  400.     char *cp;
  401.     int dots = 0;
  402.  
  403.     for (cp = s; *cp; cp++) {
  404.     if (*cp == '.')
  405.         dots++;
  406.     }
  407.     return (dots);
  408. }
  409. @
  410.